package org.opens.javaskill.jackson.annotations;

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
import org.opens.javaskill.jackson.serialize.DateSerializeTwo;
import org.opens.javaskill.jackson.serialize.NumberSerializer;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * 功能:
 *      控制json的字段的先后顺序.
 * 说明:
 *      1. 如果指定了顺序, 则必须指定alphabetic = true, 否则配置不生效使用默认配置.
 */
@Data
@JsonPropertyOrder(value = {"name", "id"}, alphabetic = true)
public class AnnotationJsonObj {

    private static Random random = new Random();

    public AnnotationJsonObj() {
    }

    public AnnotationJsonObj(Integer id, String name, Double salary, Date birthday, Date createDate) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.birthday = birthday;
        this.createDate = createDate;
    }

    /**
     * 功能:
     *      `@JsonAlias`可以使jackson的ObjectMapper对象在反序列化对象时容纳多个字段名称.
     * 说明:
     *      1. 该注解作用在json反序列化为java对象时.
     */
    @JsonAlias(value = {"id1", "id2"})
    private Integer id;

    /**
     * 功能:
     *      `@JsonProperty`注解用来控制最终json的key的名称.
     * 说明:
     *      1. 单独使用效果不佳, 与`@JsonAlias`配合使用可以使序列化更加灵活.
     *      2. `@JsonProperty`注解作用与java对象序列化为json的过程中.
     */
    @JsonAlias(value = {"full-name", "name"})
    @JsonProperty(value = "full-name")
    private String name;

    @JsonSerialize(using = NumberSerializer.class)
    private Double salary;

    /**
     * 功能:
     *      该注解可以用于简单的控制日期参数的格式.
     * 说明:
     *      1. 该注解作用与反序列化和序列化两个过程:
     *          - 在序列化对象为json时, timezone参数生效, 会将当前时间偏移8个小时, 因为北京所处东八区.
     *          - 反序列化json为对象时, timezone参数不生效, 知识简单的将json中的参数转换为时间参数,
     *      2. 这种格式化方式比较死板, 不灵活, 需要和前端沟通好传递的时间的格式.
     */
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date birthday;

    /**
     * 功能:
     *      验证两个注解都作用与序列化过程时, 哪个其作用?
     * 说明:
     *      1. 通过验证, 得出结论:
     *          - 序列化时: `@JsonSerialize`其作用;
     *          - 反序列化时: `@JsonFormat`其作用.
     *          - 总结:
     *              1. 这两个注解不冲突, 在一起出现时`@JsonSerialize`优先级高.
     * 注意:
     *      1. 如果要验证两者的优先级, 需要将`@JsonSerialize(using = DateSerializeTwo.class)`改为`@JsonSerialize(using = DateSerialize.class)`
     */
    @JsonSerialize(using = DateSerializeTwo.class)
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date createDate;

    /**
     * 功能:
     *      该注解会使序列化和反序列化过程都忽略该属性.
     * 说明:
     *      1. 该注解作用与反序列化和序列化两个过程.
     */
    @JsonIgnore
    private String ignore;

    public static AnnotationJsonObj initMethod() {
        System.out.println("init方法执行了");
        AnnotationJsonObj obj = new AnnotationJsonObj();
        obj.setId(random.nextInt(1000));
        obj.setName("老王");
        obj.setBirthday(new Date());
        obj.setCreateDate(new Date());
        obj.setSalary(random.nextDouble());
        obj.setIgnore("要忽略的字段");
        return obj;
    }

    public static List<AnnotationJsonObj> getList(int initSize) {
        List<AnnotationJsonObj> result = new ArrayList<>(initSize);
        for (int i = 0; i < initSize; i++) {
            result.add(initMethod());
        }
        return result;
    }

}
